package com.mk;

import com.mk.enums.UserTypeEnum;
import com.mk.mapper.UserMapper;
import com.mk.mapper.UserMapper2;
import lombok.SneakyThrows;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;

/**
 * @ClassName mybatis
 * @Description TODO
 * @Author makai
 * @Date 2023/10/20 22:32
 */
public class MybatisTest2
{
    /**
     * 二级缓存测试：不同的命名空间
     * 结论：二级缓存只能在同一个命名空间使用
     */
    @SneakyThrows
    @Test
    public void test()
    {
        InputStream inputStream = new FileInputStream(new File("D:\\workspace\\MybatisStudy\\src\\main\\resources\\mybatis\\mybatis-config-test.xml"));
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        mapper.getUsers2();
//        必须提交sqlsession后才能保存到二级缓存中，并且提交后一级缓存失效
        sqlSession.commit();

//另外一个命名空间
        SqlSession sqlSession2 = sqlSessionFactory.openSession();
        UserMapper2 mapper2 = sqlSession2.getMapper(UserMapper2.class);
        mapper2.getUsers2();
    }

    /**
     * 二级缓存测试：中间穿插写操作是否会清理缓存
     * 结论：会清理缓存
     */
    @SneakyThrows
    @Test
    public void test2()
    {
        InputStream inputStream = new FileInputStream(new File("D:\\workspace\\MybatisStudy\\src\\main\\resources\\mybatis\\mybatis-config-test.xml"));
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        mapper.getUsers2();
        //必须提交sqlsession后才能保存到二级缓存中，并且提交后一级缓存失效
//        sqlSession.commit();
//        mapper.update();
        mapper.getUsers2();
    }

    /**
     * 二级缓存测试：只使用select标签中useCache是否能开启二级缓存
     * 结论：useCache设置为true没有用，必须<cache/>或者在全局配置中开启二级缓存，useCache只能在全局或者是当前命名空间开启二级缓存时关闭某个查询走二级缓存
     */
    @SneakyThrows
    @Test
    public void test7()
    {
        InputStream inputStream = new FileInputStream(new File("D:\\workspace\\MybatisStudy\\src\\main\\resources\\mybatis\\mybatis-config-test.xml"));
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        SqlSession sqlSession2 = sqlSessionFactory.openSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class);
        mapper.getUsers2();
        //必须提交sqlsession后才能保存到二级缓存中，并且提交后一级缓存失效
        sqlSession.commit();
        mapper2.getUsers2();
    }

    /**
     * 一级缓存测试
     * 结论：一级缓存确实是sqlSession级别的
     */
    @SneakyThrows
    @Test
    public void test3()
    {
        InputStream inputStream = new FileInputStream(new File("D:\\workspace\\MybatisStudy\\src\\main\\resources\\mybatis\\mybatis-config-test.xml"));
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        mapper.getUsers2();
//重新创建一个sqlsession
        SqlSession sqlSession2 = sqlSessionFactory.openSession();
        UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class);
        mapper2.getUsers2();
    }

    /**
     * 一级缓存测试：两次查询之间穿插写操作
     * 结论：写操作会导致缓存被清理
     */
    @SneakyThrows
    @Test
    public void test4()
    {
        InputStream inputStream = new FileInputStream(new File("D:\\workspace\\MybatisStudy\\src\\main\\resources\\mybatis\\mybatis-config-test.xml"));
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        mapper.getUsers2();
        mapper.update();
        UserMapper mapper2 = sqlSession.getMapper(UserMapper.class);
        mapper2.getUsers2();
    }

    /**
     * 一级缓存测试：使用同一个sqlsession，调用别的mapper类进行读写
     * 结论：
     * 1.另外一个mapper类读同一个表，不能走缓存
     * 2.调用另外同一个类的写方法会导致缓存清理。
     */
    @SneakyThrows
    @Test
    public void test5()
    {
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(this.getClass().getClassLoader().getResourceAsStream("\\mybatis\\mybatis-config.xml"));
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        mapper.getUsers2();

////        调用另一个mapper
//        UserMapper2 mapper3 = sqlSession.getMapper(UserMapper2.class);
//        mapper3.update("李四");

//        提交session会清空一级缓存，提交事务，提交二级缓，flush批处理语句
        sqlSession.commit();

        UserMapper mapper2 = sqlSession.getMapper(UserMapper.class);
        mapper2.getUsers2();

    }

    /**
     * 二级缓存测试：不同的命名空间不同的mapper对同一个表进行读写，是否会导致读写不一致
     * 结论：二级缓存只有在同一个命名空间中写操作才会更新清除当前的缓存，两次读操作中间穿插了另外一个命名空间的写操作会导致第二次查询 时缓存和数据库不一致
     */
    @SneakyThrows
    @Test
    public void test6()
    {
        InputStream inputStream = new FileInputStream(new File("D:\\workspace\\MybatisStudy\\src\\main\\resources\\mybatis\\mybatis-config-test.xml"));
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        SqlSession sqlSession2 = sqlSessionFactory.openSession();
        UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class);
        ////另一个命名空间
        SqlSession sqlSession3 = sqlSessionFactory.openSession();
        UserMapper2 mapper3 = sqlSession3.getMapper(UserMapper2.class);
        mapper.getUsers2();
        //必须提交sqlsession后才能保存到二级缓存中，并且提交后一级缓存失效
        sqlSession.commit();
        //另外一个命名空间的方法修改数据
        mapper3.update("张三");
//        提交事务
        sqlSession3.commit();
        //重新查
        System.out.println(mapper2.getUsers2());
    }
}
